#include <stdio.h>
#include <iostream>
#include "MayaObject.h"
#include "variables.h"

MayaObject::MayaObject(void)
{
}


MayaObject::~MayaObject(void)
{
}


void MayaObject::addVector( glm::vec4 v){
	vertices.push_back(v);
}
void MayaObject::addFace( std::vector<GLint> face){
	faces.push_back(face);
}
void MayaObject::addNormIndex( std::vector<GLint> norm){
	norms.push_back(norm);
}
void MayaObject::addNormVect( glm::vec3 v){
	vertNorms.push_back(v);
}

void MayaObject::printInfo(){
	printf("Vertices: \n");
	for(int i=0; i< vertices.size(); i++){
		glm::vec4 v = vertices[i];
		printf("\t%d: %.2f,%.2f,%.2f,%.2f\n",(i+1),v[0],v[1],v[2],v[3]);
	}
	printf("Faces: \n");
	for(int i=0; i< faces.size(); i++){
		std::vector<GLint> v = faces[i];
		printf("\t%d: ",(i+1));
		for( int j=0; j< v.size() ; j++){
			printf("%d,",v[j]);
		}
		printf("\n");
	}
}

void MayaObject::calculateFaceNorms(){
	if( faceNorms.size() != 0){
		printf("Error: Object norms already initialized.");
		return;
	}
	if( vertNorms.size() != 0){
		//if vertex normals were specified already just
		//use those instead
		return;
	}
	for(int i=0; i< faces.size(); i++){
		std::vector<GLint> face = faces[i];
		//grab 3 vectors on the face
		glm::vec4 v0 = vertices[face[0]-1];
		glm::vec4 v1 = vertices[face[1]-1];
		glm::vec4 v2 = vertices[face[2]-1];
		glm::vec4 tmp1,tmp2;

		//calculate the norm using cross products
		tmp1 = v1-v0;
		tmp2 = v2-v0;
		glm::vec3 s1(tmp1[0],tmp1[1],tmp1[2]);
		glm::vec3 s2(tmp2[0],tmp2[1],tmp2[2]);
		
		glm::vec3 norm = glm::cross(s1,s2);
		norm = glm::normalize(norm);
		faceNorms.push_back( norm);
	}
}

//overrides GLObject::draw
void MayaObject::draw( glm::mat4 global_transform){
		  //printf("v:%d, vn:%d\n", vertices.size(), faceNorms.size());
          // Set up the object transformations 
          // And pass in the appropriate material properties
		  glLoadIdentity();
		  glm::mat4 matx = glm::transpose((this->transform)*(global_transform));
		  glLoadMatrixf(&matx[0][0]);
	     
		  //material properties
		  glUniform4fv(ambientcol ,1, this->ambient);
		  glUniform4fv(diffusecol ,1, this->diffuse );
		  glUniform4fv(specularcol ,1, this->specular );
		  glUniform4fv( emissioncol ,1, this->emission);
		  glUniform1f(shininesscol, this->shininess);

		  //if vertex normals (vn) were not specified, use face normals instead.
		  bool useVertexNormals = vertNorms.size() != 0;

          // Actually draw the object
		  for(int i=0; i< (faces.size()); i++){
				std::vector<GLint> f = faces[i];
				std::vector<GLint> n = norms[i];

				if( !useVertexNormals){
				glm::vec3 facenorm = faceNorms[i]; //do I need to transform this?
				//this will set the vertex norms to the facenorm
				glNormal3f(facenorm[0],facenorm[1],facenorm[2]);
				}

				if( f.size() == 3){ //have a special case for triangles for speed
					glBegin(GL_TRIANGLES);
					for(int j=0; j<(3); j++){
						glm::vec4 vect = vertices[ (f[j]-1) ];
						if( useVertexNormals){
							glm::vec3 norm = vertNorms[ (n[j]-1) ];
							glNormal3f(norm[0],norm[1],norm[2]);
						}
						glVertex4f(vect[0],vect[1],vect[2],vect[3] );	
					}
					glEnd();
				}else{// for general polygons
					glBegin(GL_POLYGON);
					for(int j=0; j<(f.size()); j++){
						glm::vec4 vect = vertices[ (f[j]-1) ];
						if( useVertexNormals){
							glm::vec3 norm = vertNorms[ (n[j]-1) ];
							glNormal3f(norm[0],norm[1],norm[2]);
						}
						glVertex4f(vect[0],vect[1],vect[2],vect[3] );	
					}
					glEnd();
				}
		  }
}